package com.qa.filter;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.qa.common.constant.UserConstant;
import com.qa.common.result.Result;
import com.qa.common.utils.StringRedisUtil;
import com.qa.common.utils.TokenUtil;
import com.qa.entity.User;
import io.jsonwebtoken.Claims;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;

/**
 * @author 徐
 */
@Slf4j
@Component
public class JwtAuthenticationTokenFilter implements GlobalFilter {

    @Autowired
    private StringRedisUtil redisCache;

    // 定义放行的路径
    private static final List<String> ALLOWED_PATHS = Arrays.asList(
            "/user/user/login", "/user/user/register", "/user/user/sendCode"
    );

    /**
     * @param exchange
     * @param chain
     * @return2
     */
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        // 放行
        // return chain.filter(exchange);
        ServerHttpRequest request = exchange.getRequest();

        String path = request.getURI().getPath();
        log.info("Request path: {}", path);

        // 检查路径是否在放行列表中
        for (String allowedPath : ALLOWED_PATHS) {
            if (path.contains(allowedPath)) {
                log.info("Path is allowed: {}", path);
                return chain.filter(exchange);
            }
        }
        // if (ALLOWED_PATHS.contains(path)) {
        //     log.info("Path is allowed: {}", path);
        //     return chain.filter(exchange);
        // }

        // 获取token
        List<String> tokens = request.getHeaders().get("token");

        if (tokens == null) {
            // 放行
            log.info("token == null");
            return setErrorResponse(exchange, UserConstant.USER_NOT_LOGIN);
        }
        String token = tokens.get(0);
        log.info("token=" + token);

        // 用于全局异常处理
        // HandlerExceptionResolver handlerExceptionResolver = SpringContextUtils.getBean("handlerExceptionResolver", HandlerExceptionResolver.class);

        // 解析token
        String userid;
        try {
            Claims claims = TokenUtil.parseClaim(token).getPayload();
            userid = (String) claims.get("userId");
        } catch (Exception e) {
            e.printStackTrace();
            // handlerExceptionResolver.resolveException(request, response, null, new TokenErrorException(ExceptionConstant.TOKEN_ERROR));
            // 拦截
            log.info("拦截");
            return setErrorResponse(exchange, UserConstant.LOGIN_ERROR);
        }
        // 从redis中获取用户信息
        String redisKey = "login:" + userid;
        log.info("redisKey=" + redisKey);
        String loginUserString = redisCache.getCacheObject(redisKey);
        // 将对象字符串转为对象
        User loginUser = JSONObject.parseObject(loginUserString, User.class);
        log.info("loginUser=" + loginUser);
        if (Objects.isNull(loginUser)) {
            // handlerExceptionResolver.resolveException(request, response, null, new NotLoginException(ExceptionConstant.NOT_LOGIN));
            // 拦截
            log.info("Objects.isNull(loginUser)");
            // return response.setComplete();
            return setErrorResponse(exchange, UserConstant.USER_NOT_LOGIN);
        }
        // 存入SecurityContextHolder
        // 获取权限信息封装到Authentication中
        // UsernamePasswordAuthenticationToken authenticationToken =
        //         new UsernamePasswordAuthenticationToken(loginUser, null, loginUser.getAuthorities());
        // // log.info("authorities="+loginUser.getAuthorities().toString());
        // SecurityContextHolder.getContext().setAuthentication(authenticationToken);
        // 放行
        log.info("放行");
        return chain.filter(exchange);
    }

    private Mono<Void> setErrorResponse(ServerWebExchange exchange, String msg) {
        // 1 设置状态码
        ServerHttpResponse response = exchange.getResponse();
        // response.setStatusCode(HttpStatus.UNAUTHORIZED);
        response.setStatusCode(HttpStatus.OK);
        response.getHeaders().add("Content-Type", "application/json;charset=UTF-8");
        // 错误信息
        Result<String> result = Result.loginError(msg);
        String resultJson = JSON.toJSONString(result);
        Mono<Void> voidMono = response
                .writeWith(Mono.just(response.bufferFactory().wrap(resultJson.getBytes(StandardCharsets.UTF_8))));
        // 2 结束处理
        return voidMono;
    }

}
